//
// Created by Martin on 2021/5/10.
//

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>

#include "filelock.h"

/**
 * 通过fcntl修改文件加锁/解锁方式
 */
static void filelock_set(int fd, int iswait, int l_type, int l_whence, int l_start, int l_len) {
    // 设置文件锁相关flock属性 为整个文件加锁
    struct flock flock1;
    flock1.l_type = l_type; // 写锁
    flock1.l_whence = l_whence; // 起点在文件头
    flock1.l_start = l_start;
    flock1.l_len = l_len;

    int ret = fcntl(fd, iswait, flock1);
    if (ret == -1) {
        perror("fcntl fail");
        exit(-1);
    }
}

/**
 * 文件写加锁
 * @param fd 已打开文件描述符
 * @param block 是否阻塞方式对文件加锁
 */
void filelock_lockwrite(int fd, int block) {
    int iswait = block ? F_SETLKW : F_SETLK;
    filelock_set(fd, iswait, F_WRLCK, SEEK_SET, 0, 0);
}

/**
 * 文件写解锁
 * @param fd 已打开文件描述符
 */
void filelock_unlockwrite(int fd) {
    filelock_set(fd, F_UNLCK, F_WRLCK, SEEK_SET, 0, 0);
}

/**
 * 文件读加锁
 * @param fd 已打开文件描述符
 * @param block 是否阻塞方式对文件加锁
 */
void filelock_lockread(int fd, int block) {
    int iswait = block ? F_SETLKW : F_SETLK;
    filelock_set(fd, iswait, F_RDLCK, SEEK_SET, 0, 0);
}

/**
 * 文件读解锁
 * @param fd 已打开文件描述符
 */
void filelock_unlockread(int fd) {
    filelock_set(fd, F_UNLCK, F_RDLCK, SEEK_SET, 0, 0);
}
